/*
 * Wazuh Module to analyze vulnerabilities
 * Copyright (C) 2015-2020, Wazuh Inc.
 * January 4, 2018.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef CLIENT

#ifndef WIN32

#ifndef WM_VULNDETECTOR
#define WM_VULNDETECTOR

#include "external/sqlite/sqlite3.h"
#include "wm_vuln_detector_evr.h"

#define WM_VULNDETECTOR_LOGTAG ARGV0 ":" VU_WM_NAME
#define WM_VULNDETECTOR_DEFAULT_INTERVAL 300 // 5 minutes
#define WM_VULNDETECTOR_DEFAULT_UPDATE_INTERVAL 3600 // 1 hour
#define WM_VULNDETECTOR_DEFAULT_TIMEOUT 300 // 5 minutes
#define WM_VULNDETECTOR_NVD_UPDATE_INTERVAL 86400 // 1 day
#define WM_VULNDETECTOR_DEFAULT_CPE_UPDATE_INTERVAL 86400 // 1 day
#define WM_VULNDETECTOR_RETRY_UPDATE  300 // 5 minutes
#define WM_VULNDETECTOR_ONLY_ONE_UPD UINT_MAX
#define WM_VULNDETECTOR_DOWN_ATTEMPTS  5
#define VU_DEF_IGNORE_TIME 21600 // 6 hours
#define VU_TEMP_FILE "tmp/vuln-temp"
#define VU_TEMP_FILE_BZ2 VU_TEMP_FILE ".bz2"
#define VU_FIT_TEMP_FILE VU_TEMP_FILE "-fitted"
#define VU_TEMP_METADATA_FILE VU_TEMP_FILE "-metadata"
#define VU_DEB_TEMP_FILE VU_TEMP_FILE "-deb"
#define VU_DICTIONARIES DEFAULTDIR "/queue/vulnerabilities/dictionaries"
#define VU_CPE_HELPER_FILE VU_DICTIONARIES "/cpe_helper.json"
#define VU_MSU_FILE VU_DICTIONARIES "/msu.json"
#define VU_CPEHELPER_FORMAT_VERSION 1
#define CANONICAL_REPO "https://people.canonical.com/~ubuntu-security/oval/com.ubuntu.%s.cve.oval.xml.bz2"
#define DEBIAN_REPO "https://www.debian.org/security/oval/oval-definitions-%s.xml"
#define DEBIAN_REPO_STATUS "https://security-tracker.debian.org/tracker/data/json"
#define RED_HAT_REPO_DEFAULT_MIN_YEAR 2010
#define RED_HAT_REPO_MAX_REQ_ITS 100
#define RED_HAT_REPO_MAX_FAIL_ITS 5
#define NVD_REPO_DEFAULT_MIN_YEAR 2010
#define MULTI_URL_TAG "[-]"
#define NVD_IT_COMMIT 10000
#define RED_HAT_REPO_MIN_YEAR 1999
#define NVD_REPO_MIN_YEAR 2002
#define RED_HAT_REPO_MAX_ATTEMPTS 3
#define RED_HAT_REPO_REQ_SIZE 1000
#define RHSA_DEFAULT_NUM 5
#define JSON_RED_HAT_REPO  "https://access.redhat.com/labs/securitydataapi/cve.json?after=%d-01-01&per_page=%d&page=%d"
#define RED_HAT_REPO "https://www.redhat.com/security/data/oval/v2/RHEL%s/rhel-%s-including-unpatched.oval.xml.bz2"
#define RED_HAT5_REPO "https://www.redhat.com/security/data/oval/com.redhat.rhsa-RHEL5.xml.bz2"
#define NVD_CPE_REPO "https://nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz"
#define NVD_CVE_REPO_META "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.meta"
#define NVD_CVE_REPO "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz"
#define NVD_CVE_URL "https://nvd.nist.gov/vuln/detail/"
#define MSU_REPO "https://feed.wazuh.com/vulnerability-detector/windows/msu-updates.json.gz"
#define MSU_REPO_META "https://feed.wazuh.com/vulnerability-detector/windows/msu-updates.meta"
#define NVD_REPO_MAX_ATTEMPTS 3
#define DOWNLOAD_SLEEP_FACTOR 5
#define JSON_FILE_TEST "/tmp/package_test.json"
#define DEFAULT_OVAL_PORT 443
#define KEY_SIZE OS_SIZE_6144
#define VU_SSL_BUFFER OS_MAXSTR
#define VU_MAX_VERSION_ATTEMPS 15
#define VU_MAX_WAZUH_DB_ATTEMPS 5
#define VU_MAX_TIMESTAMP_ATTEMPS 4
#define VU_MAX_VER_COMP_IT 50
#define VU_TIMESTAMP_FAIL 0
#define VU_TIMESTAMP_UPDATED 1
#define VU_TIMESTAMP_OUTDATED 2
#define VU_AGENT_REQUEST_LIMIT   3
#define VU_ALERT_HEADER "[%03d] (%s) %s"
#define VU_ALERT_JSON "1:" VU_WM_NAME ":%s"

/**
 * Default size for the CVE hash table.
 * Must be a high number for better performance.
 */
#define VU_CVE_TABLE_SIZE 4098
#define VU_SRC_NVD 1 // CVE found using the NVD as source feed.
#define VU_SRC_OVAL 2 // CVE found using an OVAL as source feed.
#define MAX_RELATED_PKGS 5 // Max number of related packages (children, siblings...)
#define MAX_PRODUCT_NAMES 4 // Max number of products available per vendor feed.

// CPE helper action flags
#define CPE_DIC_REP_VEN                                 1 << 0
#define CPE_DIC_REP_PROD                                1 << 1
#define CPE_DIC_REP_VEN_IF_MATCH                        1 << 2
#define CPE_DIC_SET_VER_IF_MATCH                        1 << 3
#define CPE_DIC_REP_PROD_IF_MATCH                       1 << 4
#define CPE_DIC_REP_SWED_IF_PROD_MATCHES                1 << 5
#define CPE_DIC_REP_MSUN_IF_VER_MATCHES                 1 << 6
#define CPE_DIC_IGNORE                                  1 << 7
#define CPE_DIC_CHECK_HOTFIX                            1 << 8
#define CPE_DIC_REP_MSUN                                1 << 9
#define CPE_DIC_SET_VER_IF_PROD_MATCHES                 1 << 10
#define CPE_DIC_SET_TARGETHW_IF_PRODUCT_MATCHES         1 << 11
#define CPE_DIC_SET_VER_ONLY_IF_PROD_MATCHES            1 << 12
#define CPE_DIC_SET_TARGETHW_ONLY_IF_PRODUCT_MATCHES    1 << 13

// Patterns for building references
#define VUL_BUILD_REF_MAX 100
#define VU_BUILD_REF_CVE_RH "https://access.redhat.com/security/cve/%s"
#define VU_BUILD_REF_BUGZ "https://bugzilla.redhat.com/show_bug.cgi?id=%s"
#define VU_BUILD_REF_RHSA "https://access.redhat.com/errata/%s"

extern const wm_context WM_VULNDETECTOR_CONTEXT;
extern const char *vu_feed_tag[];
extern const char *vu_feed_ext[];
extern const char *vu_package_comp[];
extern const char *vu_severities[];
extern const char *vu_cpe_tags[];
extern int wdb_vuldet_sock;
typedef struct cpe_list cpe_list;
typedef struct nvd_vulnerability nvd_vulnerability;
typedef struct cv_scoring_system cv_scoring_system;
typedef struct vu_cpe_dic vu_cpe_dic;
typedef struct cpe cpe;
typedef struct vu_msu_vul_entry vu_msu_vul_entry;
typedef struct vu_msu_dep_entry vu_msu_dep_entry;
typedef struct vu_msu_entries vu_msu_entries;
typedef struct vu_report vu_report;

typedef enum vu_severity {
    VU_LOW,
    VU_MEDIUM,
    VU_MODERATE,
    VU_UNKNOWN,
    VU_HIGH,
    VU_IMPORTANT,
    VU_CRITICAL,
    VU_NONE,
    VU_NEGL,
    VU_UNTR,
    VU_UNDEFINED_SEV
} vu_severity;

typedef enum vu_logic {
    VU_TRUE,
    VU_FALSE,
    VU_OR,
    VU_AND,
    VU_PACKG,
    VU_OBJ,
    VU_FILE_TEST,
    VU_VULNERABLE,
    VU_NOT_VULNERABLE,
    VU_UNDEFINED,
    VU_LESS,
    VU_HIGHER,
    VU_EQUAL,
    VU_ERROR_CMP,
    VU_NOT_FIXED,
    VU_NEED_UPDATE,
    VU_NOT_NEED_UPDATE,
    VU_INV_FEED,
    VU_TRY_NEXT_PAGE,
    VU_SUCC_DOWN_PAGE,
    VU_FINISH_FETCH
} vu_logic;

typedef enum vu_package_dist_id {
    VU_RH_EXT_8,
    VU_RH_EXT_7,
    VU_RH_EXT_6,
    VU_RH_EXT_5
} vu_package_dist_id;

typedef enum pkg_logic {
    PKG_LESS_THAN,
    PKG_LESS_THAN_OR_EQUAL,
    PKG_GREATER_THAN,
    PKG_GREATER_THAN_OR_EQUAL,
    PKG_EQUAL,
    PKG_NOT_EQUAL,
    PKG_EXISTS
} pkg_logic;

typedef enum vuln_operation {
    END_INCLUDED = 1,
    END_EXCLUDED,
    START_INCLUDED,
    START_EXCLUDED,
} vuln_operation;

typedef enum vu_cpe_dic_index {
    VU_REP_VEN,
    VU_REP_PROD,
    VU_REP_VEN_IF_MATCH,
    VU_REP_PROD_IF_MATCH,
    VU_SET_VER_IF_MATCHES,
    VU_REP_SWED_VER_IF_PR_MATCHES,
    VU_REP_MSUN_IF_VER_MATCHES,
    VU_IGNORE,
    VU_CHECK_HOTFIX,
    VU_REP_MSUN,
    VU_SET_VERSION_IF_PROD_MATCHES,
    VU_SET_TARGETHW_IF_PROD_MATCHES,
    VU_SET_VER_ONLY_IF_PROD_MATCHES,
    VU_SET_TARGETHW_ONLY_IF_PROD_MATCHES
} vu_cpe_dic_index;

typedef enum vu_feed {
    FEED_UBUNTU,
    FEED_CANONICAL,
    FEED_DEBIAN,
    FEED_REDHAT,
    FEED_JREDHAT, // JSON RedHat
    FEED_CENTOS,
    FEED_WIN,
    // Ubuntu versions
    FEED_TRUSTY,
    FEED_XENIAL,
    FEED_BIONIC,
    FEED_FOCAL,
    // Debian versions
    FEED_STRETCH,
    FEED_BUSTER,
    // RedHat versions
    FEED_RHEL5,
    FEED_RHEL6,
    FEED_RHEL7,
    FEED_RHEL8,
    // NVD
    FEED_NVD,
    FEED_CPED,
    // WINDOWS
    FEED_WS2003,
    FEED_WS2003R2,
    FEED_WXP,
    FEED_WVISTA,
    FEED_W7,
    FEED_W8,
    FEED_W81,
    FEED_W10,
    FEED_WS2008,
    FEED_WS2008R2,
    FEED_WS2012,
    FEED_WS2012R2,
    FEED_WS2016,
    FEED_WS2019,
    // OTHER
    FEED_CPEW,
    FEED_MSU,
    FEED_MAC,
    FEED_UNKNOWN
} vu_feed;

typedef enum vu_ver_comp {
    VU_COMP_L,
    VU_COMP_LE,
    VU_COMP_G,
    VU_COMP_GE,
    VU_COMP_EQ,
    VU_COMP_NEQ,
    VU_COMP_EX
} vu_ver_comp;

typedef enum cpe_tags {
    CPE_VENDOR,
    CPE_PRODUCT,
    CPE_VERSION,
    CPE_SW_EDITION,
    CPE_UPDATE,
    CPE_TARGET_HW,
    CPE_MSU_NAME
} cpe_tags;

typedef enum package_tags {
    PACKAGE_SOURCE,
    PACKAGE_NAME,
    PACKAGE_VERSION,
    PACKAGE_SOURCE_VERSION,
    PACKAGE_ARCH,
    PACKAGE_VENDOR,
} package_tags;

typedef struct cve_vuln_cond_NVD {
    int id;
    int conf_id;
    int parent;
    int children[MAX_RELATED_PKGS];
    int siblings[MAX_RELATED_PKGS];
    char *operator;
    char *start_version;
    char *end_version;
    int8_t start_operation;
    int8_t end_operation;
    bool vulnerable;
} cve_vuln_cond_NVD;

/**
 * @brief Structure that contains information on why
 * a package is affected by an speficic CVE.
 */
typedef struct cve_vuln_cond {
    char *state;
    char *operation;
    char *operation_value;
    char *condition;
} cve_vuln_cond;

/**
 * @brief Structure that contains information about
 * a package or packages affected by an speficic CVE.
 */
typedef struct cve_vuln_pkg {
    char *vendor;
    char *bin_name;
    char *src_name;
    char *arch;
    char *version;
    cve_vuln_cond_NVD *nvd_cond;
    cve_vuln_cond *vuln_cond;
    struct cve_vuln_pkg *next;
    uint8_t feed; //VU_SRC_NVD OR/AND VU_SRC_OVAL
    uint8_t discard;
} cve_vuln_pkg;

typedef struct wm_vuldet_flags {
    unsigned int enabled:1;
    unsigned int run_on_start:1;
    unsigned int update:1;
    unsigned int patch_scan:1;
    unsigned int permissive_patch_scan:1;
} wm_vuldet_flags;

typedef struct wm_vuldet_state {
    time_t next_time;
} wm_vuldet_state;

typedef struct agent_software_flags {
    unsigned int centos:1;  // Differenciate between RHEL and CentOS agents
} agent_software_flags;

typedef struct agent_software {
    char *agent_id;
    char *agent_name;
    char *agent_ip;
    cpe **agent_os_cpe;
    char *arch;
    int build;
    vu_feed dist;
    vu_feed dist_ver;
    agent_software_flags flags;
    char info;
    char *os_release;
    char *os_name;
    char *kernel_release;
    struct agent_software *next;
} agent_software;

typedef enum cve_db {
    CVE_TRUSTY,
    CVE_XENIAL,
    CVE_BIONIC,
    CVE_FOCAL,
    CVE_STRETCH,
    CVE_BUSTER,
    CVE_REDHAT5,
    CVE_REDHAT6,
    CVE_REDHAT7,
    CVE_REDHAT8,
    CVE_JREDHAT, // JSON RedHat
    CVE_NVD,
    CPE_WDIC,
    CVE_MSU,
    OS_DEPRECATED,
    OS_SUPP_SIZE
} cve_db;

typedef struct update_node {
    char *dist;
    char *version;
    vu_feed dist_ref;
    vu_feed dist_tag_ref;
    const char *dist_ext;
    time_t last_update;
    time_t interval;
    int update_from_year; // only for Red Hat and NVD feeds
    vu_logic update_state; // only for Red Hat feed
    int update_it; // only NVD feed
    char *url;
    char *multi_url;
    int multi_url_start;
    int multi_url_end;
    in_port_t port;
    char *path;
    char *multi_path;
    long timeout; // Timeout for download requests
    struct { // Supported operating systems
        char **allowed_os_name;
        char **allowed_os_ver;
    };
    unsigned int attempted:1;
    unsigned int json_format:1;
    unsigned int custom_location:1;
} update_node;

typedef struct wm_vuldet_t {
    update_node *updates[OS_SUPP_SIZE];
    time_t detection_interval;
    time_t ignore_time;
    time_t last_detection;
    agent_software *agents_software;
    int queue_fd;
    wm_vuldet_state state;
    wm_vuldet_flags flags;
} wm_vuldet_t;

typedef enum {
    V_START,
    V_OVALDEFINITIONS,
    V_DEFINITIONS,
    V_DEFINITION,
    V_CRITERIA,
    V_STATES,
    V_METADATA,
    V_GENERATOR,
    V_END
} parser_state;

// Report queue

struct vu_report {
    char *cve;
    char *title;
    char *rationale;
    char *published;
    char *updated;
    char *assigner;
    char *cve_version;
    char pending;
    char is_hotfix;
    // Impact
    char *severity;
    cv_scoring_system *cvss2;
    cv_scoring_system *cvss3;
    char *cwe;
    // References
    char **advisories;
    char **bugzilla_references;
    char **references;
    char **ref_sources;
    // Reported software
    char *software;
    char *source;
    char *generated_cpe;
    char *version;
    char *operation;
    char *operation_value;
    char *condition;
    char *arch;
    // Agent data
    char *agent_id;
    char *agent_name;
    char *agent_ip;
};

typedef struct oval_metadata {
    char *product_name;
    char *product_version;
    char *schema_version;
    char *timestamp;
} oval_metadata;

typedef struct info_state {
    char *id;
    char *operation;
    char *operation_value;
    char **arch;
    struct info_state *prev;
} info_state;

typedef struct info_obj {
    char *id;
    char *obj;
    char need_vars;
    struct info_obj *prev;
} info_obj;

typedef struct info_test {
    char *id;
    char *state;
    char *obj;
    struct info_test *prev;
} info_test;

typedef struct file_test {
    char *id;
    char *state;
    struct file_test *prev;
} file_test;

typedef struct references {
    int elements;
    char **values;
} references;

typedef struct info_cve {
    char *cveid;
    char *title; // Not available in Red Hat feed
    char *severity;
    char *published;
    char *updated;
    struct references *refs;
    char *description;
    char *cvss;
    char *cvss3;
    char *cvss_vector;
    char *cvss3_vector;
    struct references *bugzilla_references;
    struct references *advisories;
    char *cwe;
    int flags;
    struct info_cve *prev;
} info_cve;

typedef struct vulnerability {
    char *cve_id;
    char *state_id;
    char *package_name;
    int ignore;
    char **rhsa_list; // For CVEs which share a common RHSA - RedHat
    struct vulnerability *prev;
} vulnerability;

typedef struct rh_vulnerability {
    char *cve_id;
    const char *OS;
    char *OS_minor;
    char *package_name;
    char *package_version;
    struct rh_vulnerability *prev;
} rh_vulnerability;

typedef struct variables {
    char *id;
    int elements;
    char **values;
    struct variables *prev;
} variables;

struct vu_msu_entries {
    vu_msu_vul_entry *vul;
    vu_msu_dep_entry *dep;
};

typedef struct feed_metadata {
    char *size;
    char *zip_size;
    char *g_size;
    char *sha256;
    char *version;
    char *last_mod;
} feed_metadata;

typedef struct wm_vuldet_db {
    vulnerability *vulnerabilities;
    rh_vulnerability *rh_vulnerabilities;
    nvd_vulnerability *nvd_vulnerabilities;
    feed_metadata *nvd_met;
    vu_cpe_dic *w_cpes;
    vu_msu_entries msu;
    info_test *info_tests;
    file_test *file_tests;
    info_state *info_states;
    info_obj *info_objs;
    variables *vars;
    info_cve *info_cves;
    cpe_list *nvd_cpes;
    oval_metadata metadata;
    const char *OS;
} wm_vuldet_db;

// NVD - CPE structures

typedef struct translation_cond {
    const char *translation;
    const char *field;
    const char *condition;
} translation_cond;

struct cpe {
    // CPE fields
    char *part;
    char *vendor;
    char *product;
    char *version;
    char *update;
    char *edition;
    char *language;
    char *sw_edition;
    char *target_sw;
    char *target_hw;
    char *other;
    // Extra fields
    int id;
    int pos;
    char *msu_name;
    char *raw;
    char check_hotfix;
    // Multi-fields
    translation_cond *cm_product;
    cpe *next;
};

typedef struct cpe_node {
    cpe *node;
    struct cpe_node *next;
    struct cpe_node *prev;
} cpe_node;

struct cpe_list {
    cpe_node *first;
    cpe_node *last;
};

typedef struct vu_search_terms {
    char *generated_cpe;
    char *o_vendor;
    char *o_product;
    char *o_version;
    char *o_arch;
    char **vendor_terms;
    char **product_terms;
    char **version_terms;
    char **arch_terms;
    struct vu_search_terms *next;
    struct vu_search_terms *prev;
} vu_search_terms;

// NVD -CVE structures

typedef struct nvd_references {
    char *url;
    char *refsource;
    struct nvd_references *next;
} nvd_references;

typedef struct nvd_conf_cpe_match {
    int vulnerable;
    char *cpe_uri23;
    char *version_start_including;
    char *version_start_excluding;
    char *version_end_including;
    char *version_end_excluding;
    cpe *cpe_node;
    struct nvd_conf_cpe_match *next;
} nvd_conf_cpe_match;

typedef struct nvd_configuration {
    char *operator;
    struct nvd_configuration *children;
    nvd_conf_cpe_match *cpe_matches;
    struct nvd_configuration *next;
} nvd_configuration;

struct cv_scoring_system {
    char *version;
    char *vector_string;
    double base_score;
    double exploitability_score;
    double impact_score;
};

struct nvd_vulnerability {
    char *id;
    char *cwe;
    char *assigner;
    char *description;
    char *version;
    nvd_references *references;
    nvd_configuration *configuration;
    cv_scoring_system *cvss2;
    cv_scoring_system *cvss3;
    char *published;
    char *last_modified;
    struct nvd_vulnerability *next;
};

typedef struct vu_nvd_report {
    int id;
    char *raw_product;
    char *raw_version;
    char *raw_arch;
    char *generated_cpe;
    char pending;
    char vulnerable;
    char *necessary_patch;
    char *operator;
    char *version;
    char *v_start_inc;
    char *v_start_exc;
    char *v_end_inc;
    char *v_end_exc;
    char *and_package;
    struct vu_nvd_report *next;
    struct vu_nvd_report *prev;
} vu_nvd_report;

// CPE helper structures

typedef struct vu_cpe_dic_section {
    char ***vendor;
    char ***product;
    char ***version;
    char ***sw_edition;
    char ***target_hw;
    char ***msu_name;
} vu_cpe_dic_section;

typedef struct vu_cpe_dic_node {
    vu_cpe_dic_section *source;
    vu_cpe_dic_section *translation;
    unsigned int action;
    struct vu_cpe_dic_node *next;
    struct vu_cpe_dic_node *prev;
} vu_cpe_dic_node;

struct vu_cpe_dic {
    char *version;
    char *format_version;
    char *update_date;
    vu_cpe_dic_node **targets;
    char **targets_name;
};

struct vu_msu_dep_entry {
    char *patch;
    char **supers;
    struct vu_msu_dep_entry *next;
    struct vu_msu_dep_entry *prev;
};

struct vu_msu_vul_entry {
    char *cveid;
    char *patch;
    char *product;
    char *restart_required;
    char *subtype;
    char *title;
    char *url;
    int check_type;
    struct vu_msu_vul_entry *next;
    struct vu_msu_vul_entry *prev;
};

// Macros
#define wm_vuldet_is_single_provider(x) (x == FEED_UBUNTU || x == FEED_DEBIAN || x == FEED_REDHAT)
#define wm_vuldet_silent_feed(x) (x == FEED_CPEW)
#define wm_vuldet_get_json_value(obj, key) ({void *ret = NULL; cJSON *it = cJSON_GetObjectItem(obj, key); \
                                            if (it) ret = it->valuestring; ret;})
#define wm_vuldet_wdb_request(req, si) (wm_vuldet_send_wdb(req) \
                                    || wm_vuldet_recv_wdb(req, si) == OS_INVALID)
#define wm_vuldet_wdb_empty_answ(req) (!strncmp(req, "ok []", 5))
#define wm_vuldet_wdb_valid_answ(x) (!strncmp(x, "ok", 2))
// This condition may be needed in the future. By default is false
#define wm_vuldet_double_os_cpe(x) (x == FEED_UNKNOWN)
#define wm_vuldet_is_cpe_wc(x) (!strcmp(x, "*") || !strcmp(x, "-"))
#define wm_vulndet_undefined_cond(x) (!x || !strcmp(x, "-"))
#define wm_vulndet_without_r2(x) (x == FEED_WS2008 || x == FEED_WS2012)


// Function headers
int wm_vuldet_nvd_cpe_parser(char *path, wm_vuldet_db *parsed_vulnerabilities);
int wm_vuldet_insert_cpe_db(sqlite3 *db, cpe_list *node_list, char overwrite);
int wm_vuldet_sql_error(sqlite3 *db, sqlite3_stmt *stmt);
int wm_vuldet_step(sqlite3_stmt *stmt);
int wm_vuldet_prepare(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **stmt, const char **pzTail);
int wm_vuldet_get_min_cpe_index(sqlite3 *db, int *min_index);
int wm_vuldet_add_cpe(cpe *ncpe, char *cpe_raw, cpe_list *node_list, int index);
int wm_vuldet_generate_agent_cpes(sqlite3 *db, agent_software *agent, char dic);
int wm_vuldet_fetch_nvd_cve(update_node *update);
int wm_vuldet_fetch_nvd_cpe(const long timeout, char *repo);
int wm_vuldet_json_nvd_parser(char *json_feed, wm_vuldet_db *parsed_vulnerabilities);
int wm_vuldet_clean_nvd_metadata(sqlite3 *db, int year);
int wm_vuldet_insert_nvd_cve(sqlite3 *db, nvd_vulnerability *nvd_data, int year);
void wm_vuldet_free_nvd_node(nvd_vulnerability *data);
void wm_vuldet_free_nvd_list(nvd_vulnerability *nvd_it);

/**
 * @brief Correlate OVAL and NVD feeds for a more fine tuned result.
 * @param db Vulnerability detector database.
 * @param agent Agent node.
 * @param cve_table CVE hash table for a specific agent.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_linux_rm_false_positivies(sqlite3 *db, agent_software *agent, OSHash *cve_table);

/**
 * @brief For a given CVE, discard the vulnerable packages already fixed by the vendor.
 * @param db Vulnerability detector database.
 * @param agent Agent node.
 * @param cve CVE id.
 * @param first First package saved for this CVE.
 * @param vuln_discarded Vulnerabilities discarded counter.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_linux_rm_nvd_not_affected_packages(sqlite3 *db, agent_software *agent, const char *cve, cve_vuln_pkg *first, int *vuln_discarded);

/**
 * @brief For a given CVE, discard the vulnerable packages that depend on packages not installed.
 * @param cve CVE id.
 * @param first First package saved for this CVE.
 * @param vuln_discarded Vulnerabilities discarded counter.
 */
void wm_vuldet_linux_rm_nvd_not_dependencies_met_packages(const char *cve, cve_vuln_pkg *first, int *vuln_discarded);

/**
 * @brief For a given CVE, discard the vulnerable packages that have vulnerable field set to 0.
 * @param cve CVE id.
 * @param first First package saved for this CVE.
 * @param vuln_discarded Vulnerabilities discarded counter.
 */
void wm_vuldet_linux_rm_nvd_not_vulnerable_packages(const char *cve, cve_vuln_pkg *first, int *vuln_discarded);

/**
 * @brief For a given CVE, discard the vulnerable packages not fixed by the OVAL that the NVD says they are not affected.
 * @param db Vulnerability detector database.
 * @param cve CVE id.
 * @param first First package saved for this CVE.
 * @param vuln_discarded Vulnerabilities discarded counter.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_linux_rm_oval_not_affected_packages(sqlite3 *db, const char *cve, cve_vuln_pkg *first, int *vuln_discarded);

/**
 * @brief Extracts the year from a CVE id.
 * @param cve The CVE from which the year will be taken.
 * @return The CVE year.
 */
int wm_vuldet_get_cve_year(const char *cve);

/**
 * @brief Check OVAL databases to find vulnerabilities for a specific Linux agent.
 * @param db Vulnerability detector database.
 * @param agent Agent node.
 * @param cve_table CVE hash table for a specific agent.
 * @return 0 on success, 1 on silent error, -1 otherwise.
 */
int wm_vuldet_linux_oval_vulnerabilities(sqlite3 *db, agent_software *agent, OSHash *cve_table);

/**
 * @brief Check NVD database to find vulnerabilities for a specific Linux agent.
 * @param db Vulnerability detector database.
 * @param agent Agent node.
 * @param flags Configuration options.
 * @param cve_table CVE hash table for a specific agent.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_linux_nvd_vulnerabilities(sqlite3 *db, agent_software *agent, OSHash *cve_table);

/**
 * @brief Check NVD database to find vulnerabilities for a specific Windows agent.
 * @param db Vulnerability detector database.
 * @param agent Agent node.
 * @param flags Configuration options.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_win_nvd_vulnerabilities(sqlite3 *db, agent_software *agent, wm_vuldet_flags *flags);

/**
 * @brief Check if the package is vulnerable or not to a certain CVE.
 * @param version_a Package version.
 * @param operation Comparison operation.
 * @param version_b Version of the CVE to compare with @operation.
 * @param vertype Comparator to use: NVD, RPM or DEB.
 * @return 0> on success, -1 otherwise.
 */
int wm_checks_package_vulnerability(char *version_a, const char *operation, const char *version_b, version_type vertype);

/**
 * @brief Send a report for a specific CVE and the affected packages.
 * @param report An already generated report that must be parsed and sent.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_send_cve_report(vu_report *report);

/**
 * @brief Builds the string for the NVD vulnerability condition.
 * @param nvd_cond An NVD condition structure with all the necessary versions for generating the string condition.
 * @param report Report structure to be filled.
 */
void wm_vuldet_build_nvd_report_condition(cve_vuln_cond_NVD *nvd_cond, vu_report *report);

/**
 * @brief Fills the NVD CVE information in the report structure.
 * @param db Vulnerability detector database.
 * @param stmt SQLite Statement Object to prepare.
 * @param report Report structure to be filled.
 * @param cve_table_id Pointer where will be returned the id of the CVE in the database table.
 * @return SQLite error code.
 */
int wm_vuldet_fill_report_nvd_cve_info(sqlite3 *db, sqlite3_stmt *stmt, vu_report *report, int *cve_table_id);

/**
 * @brief Fills the NVD CVE references in the report structure.
 * @param db Vulnerability detector database.
 * @param stmt SQLite Statement Object to prepare.
 * @param cve_table_id The id of the CVE in the database table.
 * @param report Report structure to be filled.
 * @return SQLite error code.
 */
int wm_vuldet_fill_report_nvd_references(sqlite3 *db, sqlite3_stmt *stmt, int cve_table_id, vu_report *report);

/**
 * @brief Fills the NVD CVE cvss scoring in the report structure.
 * @param db Vulnerability detector database.
 * @param stmt SQLite Statement Object to prepare.
 * @param cve_table_id The id of the CVE in the database table.
 * @param report Report structure to be filled.
 * @return SQLite error code.
 */
int wm_vuldet_fill_report_nvd_scoring(sqlite3 *db, sqlite3_stmt *stmt, int cve_table_id, vu_report *report);

/**
 * @brief Fills the report data structure with information from the oval feeds.
 * @param db Vulnerability detector database.
 * @param stmt SQLite Statement Object to prepare.
 * @param agents_it Agent node.
 * @param pkg The package cve information.
 * @param report Report structure to be filled.
 * @return SQLite error code.
 */
int wm_vuldet_fill_report_oval_data(sqlite3 *db, sqlite3_stmt *stmt, agent_software *agents_it, cve_vuln_pkg *pkg, vu_report *report);

/**
 * @brief Traverse an agent's CVE hash table and report all CVEs.
 * @param db Vulnerability detector database.
 * @param cve_table CVE hash table for a specific agent.
 * @param agents_it Agent node.
 * @param flags Global flags to control which packages to report
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_send_agent_report(sqlite3 *db, OSHash *cve_table, agent_software *agents_it);

/**
 * @brief Free a report.
 * @param report An already generated report that has to be freed.
 */
void wm_vuldet_free_report(vu_report *report);

/**
 * @brief Free a CVE node from the CVE hash table. Each node can
 * have a linked list, so that must be handled too.
 * @param data Pointer to a CVE node.
 */
void wm_vuldet_free_cve_node(void *data);

/**
 * @brief Add a package, affected by a specific CVE, to the CVE hash table.
 * @param newPkg New package to be added.
 * @param cve Vulnerability which affects @newPkg.
 * @param cve_table CVE hash table for a specific agent.
 * @return 0 on success, -1 otherwise.
 */
int wm_vuldet_add_cve_node(cve_vuln_pkg *newPkg, const char *cve, OSHash *cve_table);

void wm_vuldet_free_cv_scoring_system(cv_scoring_system *data);
int wm_vuldet_check_timestamp(const char *target, char *timst, char *ret_timst);

/**
 * @brief Retrieve the feed's hash from the METADATA table.
 * @param Target The target feed.
 * @return The hash string.
 **/
char * wm_vuldet_get_hash(const char *target);

cpe *wm_vuldet_decode_cpe(char *raw_cpe);
int wm_vuldet_index_nvd_metadata(sqlite3 *db, int year, int cve_count, char alternative);
int wm_vuldet_remove_table(sqlite3 *db, char *table);
int wm_vuldet_clean_nvd(sqlite3 *db);
int wm_vuldet_has_offline_update(sqlite3 *db);
int wm_vuldet_clean_nvd_year(sqlite3 *db, int year);
int wm_vuldet_remove_sequence(sqlite3 *db, char *table);
char *wm_vuldet_cpe_str(cpe *cpe_s);
void wm_vuldet_free_cpe(cpe *node);
void wm_vuldet_free_multi_cpe(cpe *node);
int wm_vuldet_read(const OS_XML *xml, xml_node **nodes, wmodule *module);
void wm_vuldet_free_update_node(update_node *update);
void wm_vuldet_release_update_node(update_node **updates, cve_db node);
cpe *wm_vuldet_cpe_cpy(cpe *orig);
cpe *wm_vuldet_generate_cpe(const char *part, const char *vendor, const char *product, const char *version, const char *update, const char *edition, const char *language, const char *sw_edition, const char *target_sw, const char *target_hw, const char *other, const int id, const char *msu_name);
void wm_vuldet_free_cpe_list(cpe_list *node_list);

// Functions to manage the connection to the database
// They are not thread safe because the module is not multi-thread
int wm_vuldet_get_wdb_socket();
int wm_vuldet_send_wdb(char *msg);
int wm_vuldet_recv_wdb(char *msg, size_t size);
void wm_vuldet_close_wdb();

#endif
#endif
#endif
